use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::Instruction, rtda::Frame};


// Divide double
#[derive(Debug, Default)]
pub struct DDIV {}

impl Instruction for DDIV {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_double();
        let v1 = stack.borrow_mut().pop_double();
        let result = v1 / v2;
        stack.borrow_mut().push_double(result);
    }
}

// Divide float
#[derive(Debug, Default)]
pub struct FDIV {}

impl Instruction for FDIV {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_float();
        let v1 = stack.borrow_mut().pop_float();
        let result = v1 / v2;
        stack.borrow_mut().push_float(result);
    }
}


// Divide int
#[derive(Debug, Default)]
pub struct IDIV {}

impl Instruction for IDIV {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_int();
        let v1 = stack.borrow_mut().pop_int();
        if v2 == 0 {
            panic!("java.lang.ArithmeticException: / by zero")
        }

        let result = v1 / v2;
        stack.borrow_mut().push_int(result);
    }
}

// Divide long
#[derive(Debug, Default)]
pub struct LDIV {}

impl Instruction for LDIV {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_long();
        let v1 = stack.borrow_mut().pop_long();
        if v2 == 0 {
            panic!("java.lang.ArithmeticException: / by zero")
        }

        let result = v1 / v2;
        stack.borrow_mut().push_long(result);
    }
}